using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using MultiTCPProxy.Models;

namespace MultiTCPProxy.Services
{
    /// <summary>
    /// TCP代理服务实现类
    /// </summary>
    public class TCPProxyService
    {
        private TcpListener _listener;
        private readonly ProxyConfig _config;
        private readonly List<ProxyConnection> _connections = new List<ProxyConnection>();
        private bool _isRunning;
        private readonly object _lockObj = new object();

        public event EventHandler<ProxyEventArgs> ConnectionEstablished;
        public event EventHandler<ProxyEventArgs> ConnectionClosed;
        public event EventHandler<ProxyDataEventArgs> DataTransferred;

        public TCPProxyService(ProxyConfig config)
        {
            _config = config;
        }

        /// <summary>
        /// 启动代理服务
        /// </summary>
        public void Start()
        {
            if (_isRunning) return;

            try
            {
                _listener = new TcpListener(IPAddress.Any, _config.ListenPort);
                _listener.Start();
                _isRunning = true;
                _config.IsEnabled = true;
                _config.Status = "运行中";

                Task.Run(() => AcceptClientsAsync());
            }
            catch (Exception ex)
            {
                _config.Status = $"启动失败: {ex.Message}";
                throw;
            }
        }

        /// <summary>
        /// 停止代理服务
        /// </summary>
        public void Stop()
        {
            if (!_isRunning) return;

            _isRunning = false;
            _listener?.Stop();

            lock (_lockObj)
            {
                foreach (var connection in _connections.ToArray())
                {
                    connection.Close();
                }
                _connections.Clear();
            }

            _config.IsEnabled = false;
            _config.Status = "已停止";
            _config.ConnectionCount = 0;
        }

        private async Task AcceptClientsAsync()
        {
            while (_isRunning)
            {
                try
                {
                    var client = await _listener.AcceptTcpClientAsync();
                    var connection = new ProxyConnection(client, _config.TargetIP, _config.TargetPort);
                    
                    connection.OnClose += (s, e) =>
                    {
                        lock (_lockObj)
                        {
                            _connections.Remove(connection);
                            _config.ConnectionCount = _connections.Count;
                        }
                        ConnectionClosed?.Invoke(this, new ProxyEventArgs(_config, connection));
                    };

                    connection.OnDataTransferred += (s, e) =>
                    {
                        if (e.IsUpload)
                        {
                            _config.SentBytes += e.BytesTransferred;
                        }
                        else
                        {
                            _config.ReceivedBytes += e.BytesTransferred;
                        }
                        DataTransferred?.Invoke(this, new ProxyDataEventArgs(_config, connection, e.BytesTransferred, e.IsUpload));
                    };

                    lock (_lockObj)
                    {
                        _connections.Add(connection);
                        _config.ConnectionCount = _connections.Count;
                    }

                    connection.Start();
                    ConnectionEstablished?.Invoke(this, new ProxyEventArgs(_config, connection));
                }
                catch (Exception) when (!_isRunning)
                {
                    // 服务停止时的异常，忽略
                    break;
                }
                catch (Exception ex)
                {
                    // 记录异常但继续运行
                    Console.WriteLine($"接受连接时出错: {ex.Message}");
                }
            }
        }
    }

    /// <summary>
    /// 代理连接类，处理客户端和目标服务器之间的数据转发
    /// </summary>
    public class ProxyConnection
    {
        private readonly TcpClient _clientSocket;
        private TcpClient _serverSocket;
        private readonly string _targetIP;
        private readonly int _targetPort;
        private bool _isRunning;

        public event EventHandler OnClose;
        public event EventHandler<DataTransferredEventArgs> OnDataTransferred;

        public string ClientEndPoint => _clientSocket.Client.RemoteEndPoint.ToString();
        public DateTime ConnectedTime { get; } = DateTime.Now;

        public ProxyConnection(TcpClient clientSocket, string targetIP, int targetPort)
        {
            _clientSocket = clientSocket;
            _targetIP = targetIP;
            _targetPort = targetPort;
        }

        public void Start()
        {
            _isRunning = true;
            Task.Run(async () => await ProcessAsync());
        }

        public void Close()
        {
            if (!_isRunning) return;
            _isRunning = false;

            try
            {
                _clientSocket?.Close();
                _serverSocket?.Close();
            }
            catch { }

            OnClose?.Invoke(this, EventArgs.Empty);
        }

        private async Task ProcessAsync()
        {
            try
            {
                _serverSocket = new TcpClient();
                await _serverSocket.ConnectAsync(_targetIP, _targetPort);

                var clientStream = _clientSocket.GetStream();
                var serverStream = _serverSocket.GetStream();

                // 双向转发数据
                var task1 = ForwardDataAsync(clientStream, serverStream, true);
                var task2 = ForwardDataAsync(serverStream, clientStream, false);

                await Task.WhenAny(task1, task2);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"代理连接处理错误: {ex.Message}");
            }
            finally
            {
                Close();
            }
        }

        private async Task ForwardDataAsync(NetworkStream source, NetworkStream destination, bool isUpload)
        {
            byte[] buffer = new byte[8192];
            try
            {
                while (_isRunning)
                {
                    int bytesRead = await source.ReadAsync(buffer, 0, buffer.Length);
                    if (bytesRead == 0) break; // 连接关闭

                    await destination.WriteAsync(buffer, 0, bytesRead);
                    OnDataTransferred?.Invoke(this, new DataTransferredEventArgs(bytesRead, isUpload));
                }
            }
            catch
            {
                // 连接中断
            }
        }
    }

    public class DataTransferredEventArgs : EventArgs
    {
        public int BytesTransferred { get; }
        public bool IsUpload { get; }

        public DataTransferredEventArgs(int bytesTransferred, bool isUpload)
        {
            BytesTransferred = bytesTransferred;
            IsUpload = isUpload;
        }
    }

    public class ProxyEventArgs : EventArgs
    {
        public ProxyConfig Config { get; }
        public ProxyConnection Connection { get; }

        public ProxyEventArgs(ProxyConfig config, ProxyConnection connection)
        {
            Config = config;
            Connection = connection;
        }
    }

    public class ProxyDataEventArgs : ProxyEventArgs
    {
        public int BytesTransferred { get; }
        public bool IsUpload { get; }

        public ProxyDataEventArgs(ProxyConfig config, ProxyConnection connection, int bytesTransferred, bool isUpload)
            : base(config, connection)
        {
            BytesTransferred = bytesTransferred;
            IsUpload = isUpload;
        }
    }
}